package rpcx

import (
	"github.com/smallnest/rpcx/client"
	"github.com/smallnest/rpcx/protocol"
)

type XClient func(servicepath string) client.XClient

type option struct {
	failMode          client.FailMode
	selectMode        client.SelectMode
	preprselect       func(*Customized)
	serverMessageChan chan<- *protocol.Message
}

// WithFailMode 设置客户端调用失败时如何操作
func WithFailMode(failMode client.FailMode) func(opt *option) {
	return func(opt *option) {
		opt.failMode = failMode
	}
}

// WithSelectMode 设置客户端服务选择算法
func WithSelectMode(selectMode client.SelectMode, preprselect ...func(*Customized)) func(opt *option) {
	return func(opt *option) {
		opt.selectMode = selectMode
		if len(preprselect) > 0 {
			opt.preprselect = preprselect[0]
		}
	}
}

// WithServerMessageChan 设置客户端双向通信消息接收管道
func WithServerMessageChan(serverMessageChan chan<- *protocol.Message) func(opt *option) {
	return func(opt *option) {
		opt.serverMessageChan = serverMessageChan
	}
}

func NewXClient(discovery func(path string) *DiscoveryPlugin, opts ...func(opt *option)) XClient {
	premix := new(option)
	for i := range opts {
		opts[i](premix)
	}

	defopt := client.DefaultOption
	customized := Customized{}
	xclientstory := map[string]client.XClient{}

	// 创建rpcx客户端
	return func(servicepath string) client.XClient {
		if xclient, ok := xclientstory[servicepath]; ok {
			return xclient
		} else {
			xclientstory[servicepath] = client.NewBidirectionalXClient(
				servicepath, premix.failMode, premix.selectMode, discovery(servicepath), defopt, premix.serverMessageChan,
			)

			if premix.preprselect != nil {
				premix.preprselect(&customized)
			}

			xclientstory[servicepath].SetSelector(&customized)
		}

		return xclientstory[servicepath]
	}
}
